package org.ly.uap.client.proxy;

import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

public final class ProxyGrantingTicketStorageImpl
        implements ProxyGrantingTicketStorage {
    private final Log log = LogFactory.getLog(getClass());
    private static final long DEFAULT_TIMEOUT = 60000L;
    private final ConcurrentMap<String, ProxyGrantingTicketHolder> cache = new ConcurrentHashMap();
    private long timeout;

    public ProxyGrantingTicketStorageImpl() {
        this(60000L);
    }

    public ProxyGrantingTicketStorageImpl(long timeout) {
        this.timeout = timeout;
    }

    public String retrieve(String proxyGrantingTicketIou) {
        ProxyGrantingTicketHolder holder = (ProxyGrantingTicketHolder) this.cache.get(proxyGrantingTicketIou);

        if (holder == null) {
            this.log.info("No Proxy Ticket found for [" + proxyGrantingTicketIou + "].");
            return null;
        }

        this.cache.remove(proxyGrantingTicketIou);

        if (this.log.isDebugEnabled()) {
            this.log.debug("Returned ProxyGrantingTicket of [" + holder.getProxyGrantingTicket() + "]");
        }
        return holder.getProxyGrantingTicket();
    }

    public void save(String proxyGrantingTicketIou, String proxyGrantingTicket) {
        ProxyGrantingTicketHolder holder = new ProxyGrantingTicketHolder(proxyGrantingTicket);

        if (this.log.isDebugEnabled()) {
            this.log.debug("Saving ProxyGrantingTicketIOU and ProxyGrantingTicket combo: [" + proxyGrantingTicketIou + ", " + proxyGrantingTicket + "]");
        }
        this.cache.put(proxyGrantingTicketIou, holder);
    }

    public void cleanUp() {
        for (Map.Entry<String, ProxyGrantingTicketHolder> holder : this.cache.entrySet())
            if (( holder.getValue()).isExpired(this.timeout))
                this.cache.remove(holder.getKey());
    }

    private static final class ProxyGrantingTicketHolder {
        private final String proxyGrantingTicket;
        private final long timeInserted;

        protected ProxyGrantingTicketHolder(String proxyGrantingTicket) {
            this.proxyGrantingTicket = proxyGrantingTicket;
            this.timeInserted = System.currentTimeMillis();
        }

        public String getProxyGrantingTicket() {
            return this.proxyGrantingTicket;
        }

        final boolean isExpired(long timeout) {
            return System.currentTimeMillis() - this.timeInserted > timeout;
        }
    }
}
